﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XCommunity.Caching;
using System.Timers;
using System.Collections;

namespace XCommunity.Caching
{
  public class CacheService : IDisposable
  {

    private ICommunityContext _context;

    /// <summary>
    /// 创建缓存服务的新实例
    /// </summary>
    /// <param name="context"></param>
    public CacheService( ICommunityContext context )
    {
      _context = context;
    }


    Timer timer;

    /// <summary>
    /// 初始化服务
    /// </summary>
    public void Init()
    {

      timer = new Timer( new TimeSpan( 0, 0, 2 ).TotalMilliseconds );
      timer.Elapsed += delegate( object sender, ElapsedEventArgs e ) { OnTick(); };
      timer.Start();
    }


    private int checkTimeCount = 0;
    private int cleanTimeCount = 0;


    private void OnTick()
    {
      OnWriteCacheValue();

      if ( checkTimeCount++ > 5 )
      {
        checkTimeCount = 0;
        OnCheckCacheItems();
      }

      if ( cleanTimeCount++ > 60 )
      {
        cleanTimeCount = 0;
        OnCleanCache();
      }
    }

    private void OnCheckCacheItems()
    {

      lock ( _cacheItems )
      {

        foreach ( CacheItem item in CacheItems )
        {

          if ( !item.Available )
            continue;

          if ( !item.CheckAvailable() && item.IsWriteBackValue )
          {
            item.WriteBack( true );
          }
        }


        _cacheItems.RemoveWhere( item => !item.Available );

      }
    }


    private HashSet<CacheItem> _cacheItems = new HashSet<CacheItem>();

    protected IEnumerable<CacheItem> CacheItems
    {
      get { return _cacheItems; }
    }

    /// <summary>
    /// 新增一个缓存项
    /// </summary>
    /// <param name="cacheItem"></param>
    /// <param name="cache"></param>
    public void AddCacheItem( CacheItem cacheItem, CacheContainer cache )
    {
      cacheItem.AddTo( cache );

      lock ( _cacheItems )
      {
        _cacheItems.Add( cacheItem );
      }
    }


    /// <summary>
    /// 获取当前基准时间，所有涉及缓存项的时间需以此为准
    /// </summary>
    /// <returns></returns>
    public DateTime GetTime()
    {
      return DateTime.UtcNow;
    }

    /// <summary>
    /// 获取当前计时数，所有涉及缓存项的计时需以此为准
    /// </summary>
    /// <returns></returns>
    public long GetTicks()
    {
      return GetTime().Ticks;
    }


    public event EventHandler CleanCache;

    /// <summary>
    /// 清空所有缓存项
    /// </summary>
    protected virtual void OnCleanCache()
    {
      if ( CleanCache != null )
        CleanCache( this, EventArgs.Empty );
    }


    private void OnWriteCacheValue()
    {

      lock ( CacheItems )
      {
        foreach ( CacheItem item in CacheItems )
        {
          item.TryWriteBack();
        }
      }
    }


    /// <summary>
    /// 从缓存服务中移除一个缓存项
    /// </summary>
    /// <param name="item"></param>
    public void RemoveCacheItem( CacheItem item )
    {
      lock ( _cacheItems )
      {
        _cacheItems.Remove( item );
      }
    }


    public void Dispose()
    {
      if ( timer != null )
        timer.Dispose();
    }

  }
}
